package cn.sunshine.ymcc.service.impl;

import cn.sunshine.ymcc.CourseDoc;
import cn.sunshine.ymcc.dto.AggrTermsBucket;
import cn.sunshine.ymcc.dto.CourseESSearchDto;
import cn.sunshine.ymcc.mapper.HighlightResultMapper;
import cn.sunshine.ymcc.repository.CourseEsRepository;
import cn.sunshine.ymcc.result.PageList;
import cn.sunshine.ymcc.service.ICourseEsService;
import cn.sunshine.ymcc.utils.AggsPageList;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CourseEsServiceImpl implements ICourseEsService {
    @Autowired
    private CourseEsRepository courseEsRepository;
    @Autowired

    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    // 引入结果映射器处理高亮的mapper
    @Autowired
    private HighlightResultMapper highlightResultMapper;

    @Override
    public void saveCourse(CourseDoc doc) {
        courseEsRepository.save(doc);
    }

    @Override
    public void delete(Long id) {
        courseEsRepository.deleteById(id);

    }

    /*
     * @Title: search
     * @Description: 高级查询
     * @Author: Mr.Jiang
     * @Version: 1.0
     * @Date:  2022/8/15 11:57
     * @Parameters: [courseESSearchDto]
     * @Return cn.sunshine.ymcc.result.PageList<cn.sunshine.ymcc.CourseDoc>
     */
    @Override
    public PageList<CourseDoc> search(CourseESSearchDto courseESSearchDto) {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //分页条件查询
        builder.withPageable(PageRequest.of(courseESSearchDto.getPage() - 1, courseESSearchDto.getRows()));
        //排序规则
        if(StringUtils.hasLength(courseESSearchDto.getSortField())){
        String sortName = "";
        switch (courseESSearchDto.getSortField().toLowerCase()) {
            case "xl":
                sortName = "saleCount";
                break;
            case "pl":
                sortName = "commentCount";
                break;
            case "xp":
                sortName = "onlineTime";
                break;
            case "jg":
                sortName = "price";
                break;
            case "rq":
                sortName = "viewCount";
                break;
        }
        if (StringUtils.hasLength(sortName)) {
            SortOrder order = SortOrder.ASC;
            if (StringUtils.hasLength(courseESSearchDto.getSortType())) {
                order = courseESSearchDto.getSortType().equals("desc") ? SortOrder.DESC : SortOrder.ASC;
            }
            builder.withSort(SortBuilders.fieldSort(sortName).order(order));

        }}
        // 添加聚合查询:按照等级聚合
        builder.addAggregation(AggregationBuilders.terms("gradeNames").field("gradeName.keyword"));
        builder.addAggregation(AggregationBuilders.terms("chargeNames").field("chargeName.keyword"));


        // 搜索条件 keyWord（高亮和聚合版本）
       /* private Long courseTypeId;
        private String gradeName;
        private Double priceMax;
        private Double priceMin;
        */
        // 构建组合查询
        // 1.构建Bool
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (StringUtils.hasLength(courseESSearchDto.getKeyword())) {
            // 课程名字keyword
            boolQueryBuilder.must(QueryBuilders.matchQuery("name", courseESSearchDto.getKeyword()));
        }
        if (courseESSearchDto.getCourseTypeId() != null) {
            // 精准查找之课程类型IDcourseTypeId
            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId", courseESSearchDto.getCourseTypeId()));
        }
        if (StringUtils.hasLength(courseESSearchDto.getGradeName())) {
            // 精准查找之课程等级GradeName
            boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName.keyword", courseESSearchDto.getGradeName()));
        }
        // 设置价格区间
        if (courseESSearchDto.getPriceMin() != null) {
            // 精准查找之课程最小价格
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(courseESSearchDto.getPriceMin()));
        }
        if (courseESSearchDto.getPriceMax() != null) {
            // 精准查找之课程最高价格
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(courseESSearchDto.getPriceMax()));
        }
        
        // 高亮搜索条件
        HighlightBuilder.Field  highlightField = new HighlightBuilder.Field("name")
                .preTags("<span style='color:red'>")
                .postTags("</span>");

        builder.withHighlightFields(highlightField);



        //查询
        // s设置条件查询
        //builder.addAggregation()
        builder.withQuery(boolQueryBuilder);
        NativeSearchQuery build = builder.build();

        // 处理高亮
        AggregatedPage<CourseDoc> page = elasticsearchRestTemplate.queryForPage(build, CourseDoc.class, highlightResultMapper);

      // 处理聚合
        Aggregations aggregations = page.getAggregations(); // 1.获取所有的聚合结果集
        // 2.结果集用map接收
        Map<String, Aggregation> aggsMap = aggregations.asMap();
        ParsedStringTerms gradeNameAgg = (ParsedStringTerms)aggsMap.get("gradeNames");

        ParsedStringTerms chargeNameAgg = (ParsedStringTerms)aggsMap.get("chargeNames");
        List<? extends Terms.Bucket> buckets = gradeNameAgg.getBuckets();
        Map<String, List<AggrTermsBucket>> map = new HashMap<>();

        //等级聚合结果处理
      /*  List<AggrTermsBucket> gradeNameAggList = gradeNameAgg.getBuckets().stream()
                .map(bucket -> new AggrTermsBucket(bucket.getKeyAsString(), bucket.getDocCount()))
                .collect(Collectors.toList());*/

        ArrayList<AggrTermsBucket> gradeNameAggList = new ArrayList<>();
        for ( Terms.Bucket bt:buckets) {
            AggrTermsBucket aggrTermsBucket = new AggrTermsBucket();
            aggrTermsBucket.setKey(bt.getKeyAsString());
            aggrTermsBucket.setDocCount(bt.getDocCount());
            gradeNameAggList.add(aggrTermsBucket);
        }
        //收费规则聚合结果处理
        List<AggrTermsBucket> chargeNameAggList = chargeNameAgg.getBuckets().stream()
                .map(bucket -> new AggrTermsBucket(bucket.getKeyAsString(), bucket.getDocCount()))
                .collect(Collectors.toList());
        map.put("gradeNames",gradeNameAggList);
        map.put("chargeNames",chargeNameAggList);

        // Page<CourseDoc> page = courseEsRepository.search(build);
        return new AggsPageList(page.getTotalElements(), page.getContent(),map);

    }



// 没有高亮和聚合的版本
   /* // 搜索条件 keyWord
        private String courseTypeId;
        private String gradeName;
        private String priceMax;
        private String priceMin;


    // 构建组合查询
    // 1.构建Bool
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (StringUtils.hasLength(courseESSearchDto.getKeyword())) {
        // 课程名字keyword
        boolQueryBuilder.must(QueryBuilders.matchQuery("name", courseESSearchDto.getKeyword()));
    }
        if (courseESSearchDto.getCourseTypeId() != null) {
        // 精准查找之课程类型IDcourseTypeId
        boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId", courseESSearchDto.getCourseTypeId()));
    }
        if (StringUtils.hasLength(courseESSearchDto.getGradeName())) {
        // 精准查找之课程等级GradeName
        boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName", courseESSearchDto.getGradeName()));
    }
    // 设置价格区间
        if (courseESSearchDto.getPriceMin() != null) {
        // 精准查找之课程最小价格
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(courseESSearchDto.getPriceMin()));
    }
        if (courseESSearchDto.getPriceMax() != null) {
        // 精准查找之课程最高价格
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(courseESSearchDto.getPriceMax()));
    }

    //查询
    // s设置条件查询
        builder.withQuery(boolQueryBuilder);
    NativeSearchQuery build = builder.build();
    Page<CourseDoc> page = courseEsRepository.search(build);
        return new PageList<>(page.getTotalElements(), page.getContent());*/
}
